package com.appspot.smartgan.server;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutionException;

import org.apache.commons.lang3.StringEscapeUtils;
import org.json.JSONException;
import org.json.JSONObject;

import com.appspot.smartgan.Messages;
import com.appspot.smartgan.util.Child;
import com.appspot.smartgan.util.Message;

import android.os.AsyncTask;
import android.text.Html;
import android.util.Log;

/**
 * 
 * @author Dor Mesica
 */
public class HttpClient extends AbstractClient {

	private static final String FIELD_TITLE = "title";
	
	private static final String FIELD_MESSAGE = "msg";
	
	private static final String FIELD_DATE = "date";
	
	private static final String FIELD_TO_TEACHER = "to_teacher";
	
	private static final String FIELD_IMAGE_URL = "img";
	
	
	/**
	 * Creates a new instance of the HttpConnection
	 * class.
	 * @param url The url the class should connect to.
	 */
	public HttpClient(String url, int responseType) {
		super(url, responseType);
	}
	
	/**
	 * Sends the given URL, and retrieves the
	 * response.
	 */
	@Override
	public void execute() {
		AsyncTask<String, String, String> connection;
		connection = new AsyncConnection().execute(URL);
		
		try {
			// get the response string
			String responseString = connection.get();
			
			if (responseString.isEmpty()) {
				response = null;
			} else {
				// extract data from response string
				if (responseType == Client.RESPONSE_BOOLEAN) {
					response = extractBooleanResponse(responseString);
				} else if (responseType == Client.RESPONSE_LIST) {
					response = extractListResponse(responseString);
				} else if (responseType == Client.RESPONSE_JSON) {
					response = extractJSONResponse(responseString);
				} else if (responseType == Client.RESPONSE_JSON_STRING) {
					response = extractStringFromJson(responseString);
				} else if (responseType == Client.RESPONSE_PUBLIC_MESSAGES || 
						responseType == Client.RESPONSE_PRIVATE_MESSAGES) {
					response = extractMessages(responseString);
				} else if (responseType == Client.RESPONSE_ID_LIST) {
					response = responseString.split("\\,");
				} else {
					response = responseString;
				}
			}
		} catch (InterruptedException e) {
			Log.e("SMARTGAN", "InterruptedException: " + e.getMessage());
		} catch (ExecutionException e) {
			Log.e("SMARTGAN", "ExecutionException: " + e.getMessage());
		}
	}

	private Object extractJSONResponse(String responseString) {
		if (responseString.equals("-1")) {
			return null;
		}
		
		JSONObject json = null;
		
		try {
			json = new JSONObject(responseString);
		} catch (JSONException e) {
			Log.e("SMARTGAN", e.getMessage());
		}
		return json;
	}

	private Object extractListResponse(String responseString) {
		if (responseString.equals("-1")) {
			return null;
		}
		
		List<Child> lst = new ArrayList<Child>();
		int index = 1;
		
		while (responseString.charAt(index) != '}') {
			String str1 = "";
			String str2 = "";
			
			// read every char until :
			while (responseString.charAt(index) != ':') {
				str1 += responseString.charAt(index);
				index++;
			}
			index++;	// skip the ':'
			
			// read the rest until ',' or '}'
			while ((responseString.charAt(index) != ',') && 
					(responseString.charAt(index) != '}')) {
				str2 += responseString.charAt(index);
				index++;
			}
			
			// if you have more than one child skip the ',' 
			if (responseString.charAt(index) == ',')
				index++;
			
		 	str1 = eliminateIrrelevantCharacters(str1);
		 	str2 = eliminateIrrelevantCharacters(str2);
		 	Child c = null;

		 	str2 = StringEscapeUtils.unescapeJava(str2);
		 	c = new Child(str1, "", str2);

			lst.add(c);
		}
		
		return lst;
	}

	private Object extractBooleanResponse(String responseString) {
		if (responseString.equals("-1")) {
			return Boolean.valueOf(false);
		}
		
		return Boolean.valueOf(true);
	}
	
	private String extractStringFromJson(String responseString) {
		if (responseString.equals("-1")) {
			return null;
		}
		
		JSONObject json = null;
		
		try {
			json = new JSONObject(responseString);
			return json.getString("KG_id");
		} catch (JSONException e) {
			Log.e("SMARTGAN", e.getMessage());
		}
		
		return null;
	}
	
	private List<Message> extractMessages(String responseString) {
		// if -1 return empty list
		if (responseString.equals("[]") || responseString.equals("-1")) {
			return new LinkedList<Message>();
		}
		
		// date format to parse date
		SimpleDateFormat formatter = 
				new SimpleDateFormat(Messages.DATE_FORMAT, Locale.ENGLISH);
		
		String temp = "";
		List<Message> lst = new LinkedList<Message>();
		
		for (int i = 0; i < responseString.length(); i++) {
			temp = "";
			
			if (responseString.charAt(i) != '{') {
				continue;
			}
			
			// responseString.charAt(i) == '{'
			while (responseString.charAt(i) != '}') {
				if (responseString.charAt(i) == '\\' && 
						responseString.charAt(i+1) == '"') {
					temp += '"';
					i++;
				} else {
					temp += responseString.charAt(i);
				}
				i++;
			}
			temp += '}';
			
			try {
				JSONObject messageJson = new JSONObject(temp);
				
				// get title and message
				String title = messageJson.getString(FIELD_TITLE);
				title = Html.fromHtml(title).toString();
				title = StringEscapeUtils.unescapeJava(title);
				
				String message = messageJson.getString(FIELD_MESSAGE);
				message = Html.fromHtml(message).toString();
				message = StringEscapeUtils.unescapeJava(message);
				
				// extract the date in which the message was sent
				Date date = new Date();
				try {
					date = formatter.parse(messageJson.getString(FIELD_DATE));
				} catch (ParseException e) {
					Log.e("SMARTGAN", e.getMessage());
				}
				
				// create the message with the above title, message and date
				Message messageObject = new Message(title, message, date);
				
				// if private message, find if was sent by user or teacher 
				if (responseType == RESPONSE_PRIVATE_MESSAGES) {
					String toTeacher = messageJson.getString(FIELD_TO_TEACHER);
					messageObject.setToTeacher(toTeacher.equals("true"));
				}
				
				// find image url
				if (messageJson.has(FIELD_IMAGE_URL)) {
					String imageUrl = messageJson.getString(FIELD_IMAGE_URL);
					if (!imageUrl.equals("null")) {
						messageObject.setImageUrl(imageUrl);
					}
				}
				
				// add message to list
				lst.add(messageObject);
			} catch (JSONException e) {
				Log.e("SMARTGAN", e.getMessage());
			}
		}
		
		return lst;
	}

	private static String eliminateIrrelevantCharacters(String input) {
		int index = 2;
		String str = "";
		if (input.charAt(index) == '\'')
			index++;
		
		while (input.charAt(index) != '\'') {
			str += input.charAt(index);
			index++;
		}
		
		return str;
	}

}
